(function(window, document) {
	/**
	 * @function getRootElement  获取根节点
	 * @param {HTMLElement|String} select DOM节点或者选择器
	 * @return {HTMLElement|Node} DOM节点
	 * */
	function getRootElement(select) {
		if (select.nodeType === 1) {
			return select;
		}
		return document.querySelectorAll(select)[0];
	}

	/**
	 * @function getChildElement 获取子节点
	 * @param {HTMLElement|String} parent 父元素节点
	 * @param {HTMLElement|String} select  子元素节点
	 * @return {HTMLElement|NodeList} DOM节点
	 * */
	function getChildElement(parent, select) {
		return getRootElement(parent).querySelectorAll(select);
	}

	/**
	 * @function addTransition  添加transition动画
	 * @param {HTMLElement} element 需要执行动画的DOM节点
	 * @param {Number} duration 设置执行动画的时间
	 * */
	function addTransition(element, duration) {
		element.style.transition = `transform ${duration}ms`;
		element.style.webkitTransition = `transform ${duration}ms`;
	}

	/**
	 * @function addTransition  取消transition动画
	 * @param {HTMLElement} element 需要取消动画的DOM节点
	 * */
	function removeTransition(element) {
		element.style.transition = `none`;
		element.style.webkitTransition = `none`;
	}

	/**
	 * @function addTransition  添加transition动画
	 * @param {HTMLElement} element 需要设置偏移的DOM节点
	 * @param {Number} distance 设置执行偏移的距离
	 * */
	function setTranslate(element, distance) {
		element.style.transform = `translate3d(${distance}px, 0, 0)`;
		element.style.webkitTransform = `translate3d(${distance}px, 0, 0)`;
	}

	/**
	 * @function setClass 设置class类名
	 * @param {HTMLElement} element 需要设置类名的DOM节点
	 * @param {String} className 需要设置的类名
	 * 当element存在相同的class类名时，直接返回，否则进行设置
	 * */
	function setClass(element, className) {
		if(element) {
			let otherClassName = element.className.split(' ');
			let index = otherClassName.indexOf(className);
			if (index === -1) {
				otherClassName.push(className);
				element.className = otherClassName.join(' ');
			}
		}
	}

	/**
	 * @function removeClass 删除class类名
	 * @param {HTMLElement} element 需要删除类名的DOM节点
	 * @param {String} className 需要删除的类名
	 * 当element内存在类名则删除，不存在则返回
	 * */
	function removeClass(element, className) {
		let allClassName = element.className.split(' ');
		let index = allClassName.indexOf(className);
		let newClassName;
		if (index > -1) {
			allClassName.splice(index, 1);
			newClassName = allClassName.join(' ');
		} else {
			newClassName = allClassName.join(' ');
		}
		element.className = newClassName;
	}

	/**
	 * @function onEvent addEventListener监听事件
	 * 兼容性处理
	 * */
	function onEvent(element, event, callback) {
		if (element.addEventListener) {
			element.addEventListener(event, callback, false);
		} else if (element.attachEvent) {
			element.attachEvent('on' + event, callback);
		} else {
			element['on' + event] = callback;
		}
	}

	/**
	 * @function onEvent removeEventListener取消监听事件
	 * 兼容性处理
	 * */
	function removeEvent(element, event, callback) {
		if (element.addEventListener) {
			element.removeEventListener(event, callback, false);
		} else if (element.attachEvent) {
			element.detachEvent('on' + event, callback);
		} else {
			element['on' + event] = null;
		}
	}

	/**
	 * @class HSwipe
	 * @param {Object} option 轮播图配置
	 * @param {HTMLElement|String} option.el 轮播图外层容器
	 * @param {HTMLElement|String} option.wrapper 轮播图wrapper容器
	 * @param {HTMLElement|String} option.slide 轮播图slide容器
	 * @param {Number} option.activeIndex 初始激活的图像
	 * @param {Number} option.duration  动画消耗时间
	 * @param {Number} option.interval  每帧停留时间
	 * @param {Object} option.pagination 配置分页器
	 * @param {String} option.pagination.el 分页器选择器
	 * @param {String} option.pagination.tagName  分页器生成的标签
	 * @param {String} option.pagination.pageName  分页器的使用类名
	 * @param {String} option.pagination.activeClass 分页器激活使用的类名
	 * @param {Function} option.transitionEnd 每次动画执行完成之后的回调函数，第一个参数为当前激活的索引
	 * @return {Object} HSwipe 实例化一个HSwipe对象
	 * */
	const nameSpace = 'h-swipe';
	console.log('%c swipe from 郝晨光！！！', 'color:white;font-size:14px;text-shadow: 0px 0px 5px red;');

	function HSwipe(option) {
		if (this instanceof HSwipe) {
			return this._init(option);
		} else {
			return new HSwipe(option);
		}
	}

	/**
	 * @method _init
	 * 初始化轮播图的配置
	 * */
	HSwipe.prototype._init = function (option) {
		this._option = option; // 保存初始化配置
		this.container = getRootElement(this._option.el || `.${nameSpace}-container`); // 外层容器
		this.currentIndex = this._option.activeIndex || 0; // 当前显示的图片的原始下标
		this.activeIndex = this._option.activeIndex? this._option.activeIndex + 1 : 1; // 当前激活的图片的轮播下标
		this.duration = this._option.duration || 800; // 动画时间
		this.interval = this._option.interval || 2000; // 间隔时间
		this.execute = this.duration + this.interval; // 定时器的执行时间
		this.$transitionEnd = this._option.transitionEnd;
		this._initStyle();
		this.refresh(); // 刷新轮播图
	};

	/**
	 * @method _formatHSwipe 格式化HSwipe
	 * 初始化DOM节点的尺寸
	 * */
	HSwipe.prototype._formatHSwipe = function () {
		this.wrapper = getChildElement(this.container, this._option.wrapper || `.${nameSpace}-wrapper`)[0]; // 图片轮播容器
		let slides = getChildElement(this.wrapper, this._option.slide || `.${nameSpace}-slide`);
		this.slideWidth = this.container.offsetWidth; // 获取图片的宽度
		let len = slides.length; // 保存原始的slide长度
		this.wrapper.style.width = this.slideWidth * (len + 2) + 'px'; // 设置wrapper的宽度为每一项的宽度 * 总图片长度 + 2；即最终处理的 n + 2 模式的长度；使其能容纳所有图片
		if (!this.disguise) {
			this.slides = getChildElement(this.wrapper, this._option.slide || `.${nameSpace}-slide`); // 需要轮播的每一个slide
			this.len = this.slides.length; // 保存原始的slide长度
			if (this.len === 0) return; // 如果当前图片长度为0，则不进行刷新轮播
			// 标识，判断是否需要重新获取DOM节点和数据
			let endDisguise = this.slides[0].cloneNode(true); // 克隆第一张图片
			let startDisguise = this.slides[this.len - 1].cloneNode(true); // 克隆最后一张图片
			this.wrapper.appendChild(endDisguise); // 将克隆的第一张图片添加到尾部
			this.wrapper.insertBefore(startDisguise, this.slides[0]); // 将克隆的最后一张图片添加到头部
			this.disguise = true;
		}
		let distance = this.slideWidth * (-this.activeIndex); // 计算下一次的位置
		setTranslate(this.wrapper, distance); // 设定初始化的位置
		this._slides = getChildElement(this.wrapper, this._option.slide || `.${nameSpace}-slide`); // 重新获取所有的图片，保存在私有属性当中，并遍历设置宽度
		for (let i = 0; i < this._slides.length; i++) {
			this._slides[i].style.width = this.slideWidth + 'px';
		}
		// 如果有分页器配置的话，初始化分页器
		if (this._option.pagination) {
			if (typeof this._option.pagination === 'boolean') {
				this._option.pagination = {};
			}
			this._formatHSwipePagination();
		}
	};

	/**
	 * @method _formatHSwipePagination 初始化分页器
	 * */
	HSwipe.prototype._formatHSwipePagination = function () {
		this.pagination = getChildElement(this.container, this._option.pagination.el || `.${nameSpace}-pagination`)[0]; // 分页器容器
		// 删除所有之前存在的分页，避免出现重复渲染
		for (let i = 0; this.pageBtns && i < this.pageBtns.length; i++) {
			this.pagination.removeChild(this.pageBtns[i]);
		}
		// 遍历生成新的分页器
		for (let i = 0; i < this.len; i++) {
			let pageBtn = document.createElement(this._option.pagination.tagName || 'span'); // 生成DOM节点，默认为 span
			pageBtn.className = this._option.pagination.pageName || `${nameSpace}-page-btn`; // 给DOM节点绑定类名，默认为HSwipe-page-btn
			this.pagination.appendChild(pageBtn); // 追加到DOM内
		}
		this.pagination.style.marginLeft = -this.pagination.offsetWidth / 2 + 'px'; // 设置pagination容器的位置
		let pageBtnsSelect = this._option.pagination.pageName ? '.' + this._option.pagination.pageName : `.${nameSpace}-page-btn`;
		this.pageBtns = getChildElement(this.pagination, pageBtnsSelect); // 获取新的分页器
		this._pageActive(); // 激活page-btn
	};

	/**
	 * @method _formatIndex
	 * 重置activeIndex和currentIndex
	 * */
	HSwipe.prototype._formatIndex = function () {
		// 判断当前的activeIndex是否大于图片长度
		if (this.activeIndex > this.len) {
			this.activeIndex = 1;
			// 判断当前的activeIndex是否小于等于 0
		} else if (this.activeIndex <= 0) {
			this.activeIndex = this.len;
		}
		// 判断，使currentIndex始终指向正确的index索引值
		if (this.activeIndex > this.len || this.activeIndex === 1) {
			this.currentIndex = 0;
		} else if (this.activeIndex === 0 || this.activeIndex === this.len) {
			this.currentIndex = this.len - 1;
		}
	};

	HSwipe.prototype._initStyle = function() {
		let style = document.createElement('style');
		style.type = 'text/css';
		style.innerText = `.h-swipe-container {position: relative;width: 100%;overflow: hidden;}.h-swipe-wrapper {width: 100%;}.h-swipe-wrapper::after {content: '';clear: both;display: block;height: 0;overflow: hidden;}.h-swipe-slide {width: 100%;float: left;}.h-swipe-slide img {width: 100%;}.h-swipe-pagination {position: absolute;display: flex;align-items: center;bottom: 10%;left: 50%;}.h-swipe-page-btn {width: 8px;height: 4px;border-radius: 4px;margin: 0 5px;background: #fff;opacity: 0.5;transition: all .3s;}.h-swipe-page-btn.active {width: 14px;opacity: 1;}`;
		document.head.appendChild(style);
	};

	/**
	 * @method refresh
	 * 刷新轮播图
	 * */
	HSwipe.prototype.refresh = function () {
		this._formatHSwipe();
		this.off(); // 先关闭之前开启的事件
		this.$transitionEnd = this._option.transitionEnd;
		this.timer = setInterval(this._move.bind(this), this.execute); // 开启定时器
		this._event(); // HSwipe的事件
	};

	/**
	 * @method _move
	 * 轮播图移动
	 * */
	HSwipe.prototype._move = function () {
		// 使activeIndex和currentIndex自增
		this.activeIndex++;
		this.currentIndex++;
		let distance = this.slideWidth * (-this.activeIndex); // 计算下一次的位置
		addTransition(this.wrapper, this.duration);
		setTranslate(this.wrapper, distance);
		this._formatIndex(); // 判断index是否需要重置
		this._pageActive(); // page-btn激活
	};

	/**
	 * @method _transitionEnd
	 * 动画结束以后执行
	 * */
	HSwipe.prototype._transitionEnd = function () {
		let distance = this.slideWidth * (-this.activeIndex); // 计算下一次的位置
		removeTransition(this.wrapper); // 删除transition
		setTranslate(this.wrapper, distance); // 设置偏移
		if (this._option.transitionEnd) {
			setTimeout(() => {
				this.$transitionEnd.call(this, this.currentIndex);
			});
		}
	};

	/**
	 * @method _pageActive  分页器使用类名激活
	 * */
	HSwipe.prototype._pageActive = function () {
		// 先遍历删除所有的激活类名
		for (let i = 0; this.pageBtns.length && i < this.pageBtns.length; i++) {
			removeClass(this.pageBtns[i], this._option.pagination.activeClass || 'active');
		}
		if(this.pageBtns.length) {
			// 给对应的page-btn设置active类名
			setClass(this.pageBtns[this.currentIndex], this._option.pagination.activeClass || 'active');
		}
	};

	/**
	 * @method _touchStart
	 * @param {event} e
	 * 触摸开始
	 * */
	HSwipe.prototype._touchStart = function (e) {
		// 如果是多个手指按下，直接返回，不触发事件,或者当前的slide长度小于3的时候，不支持滑动
		if (e.touches.length > 1 || this.len < 3) {
			return;
		}
		clearInterval(this.timer); // 清除定时器
		this.touchStartX = e.touches[0].clientX - this.container.offsetLeft; // 保存初始触碰位置
		this.touchStartTime = e.timeStamp; // 保存初始触碰时间
	};

	/**
	 * @method _touchMove
	 * @param {event} e
	 * 触摸移动
	 * */
	HSwipe.prototype._touchMove = function (e) {
		// 移动的距离
		let touchMoveX = e.touches[0].clientX - this.touchStartX; // 计算手指滑动的距离
		let distance = -this.activeIndex * this.slideWidth + touchMoveX; //  计算当前设置的偏移量
		removeTransition(this.wrapper); // 删除transition
		setTranslate(this.wrapper, distance); // 设置偏移
	};

	/**
	 * @method _touchEnd
	 * @param {event} e
	 * 触摸结束
	 * */
	HSwipe.prototype._touchEnd = function (e) {
		this.touchEndX = e.changedTouches[0].clientX; // 保存当前手指离开的位置
		this.touchEndTime = e.timeStamp; // 保存手指离开的时间
		// 当滑动时间小于150的时候，切换图片
		let direction = this.touchStartX - this.touchEndX; // 正数是向左，负数是向右
		if (this.touchEndTime - this.touchStartTime <= 150 || Math.abs(direction) >= this.slideWidth / 2) {
			if (direction > 0) {
				this.activeIndex++;
				this.currentIndex++;
			} else {
				this.activeIndex--;
				this.currentIndex--;
			}
		}
		let distance = this.slideWidth * (-this.activeIndex); // 计算下一次的位置
		addTransition(this.wrapper, this.duration); // 添加transition
		setTranslate(this.wrapper, distance); // 设置偏移
		this._formatIndex(); // 判断是否需要重置activeIndex和currentIndex
		this._pageActive(); // 设置page-btn激活样式
		clearInterval(this.timer); // 清除定时器
		this.timer = setInterval(() => this._move(), this.execute); // 重新开启定时器
	};

	/**
	 * @method _event  HSwipe事件监听
	 * 开启HSwipe的事件
	 * */
	HSwipe.prototype._event = function () {
		this._touchStart = this._touchStart.bind(this); // 绑定事件的this指向，以及保存事件为具名函数，用于清除事件，避免重复触发
		this._touchMove = this._touchMove.bind(this);
		this._touchEnd = this._touchEnd.bind(this);
		this._transitionEnd = this._transitionEnd.bind(this);
		this.refresh = this.refresh.bind(this);
		onEvent(this.wrapper, 'touchstart', this._touchStart); // 触摸屏幕
		onEvent(this.wrapper, 'touchmove', this._touchMove); // 触摸移动
		onEvent(this.wrapper, 'touchend', this._touchEnd); // 触摸结束
		onEvent(this.wrapper, 'transitionEnd', this._transitionEnd); // 动画结束
		onEvent(this.wrapper, 'webkitTransitionEnd', this._transitionEnd); // 动画结束
		onEvent(window, 'resize', this.refresh); // resize重新计算尺寸
	};

	/**
	 * @method off 关闭HSwipe
	 * @return {null} 返回 null
	 * 清除定时器，清除所有绑定的事件
	 * */
	HSwipe.prototype.off = function () {
		clearInterval(this.timer);
		this.$transitionEnd = () => {
		};
		removeEvent(this.wrapper, 'touchstart', this._touchStart); // 触摸屏幕
		removeEvent(this.wrapper, 'touchmove', this._touchMove); // 触摸移动
		removeEvent(this.wrapper, 'touchend', this._touchEnd); // 触摸结束
		removeEvent(this.wrapper, 'transitionEnd', this._transitionEnd); // 动画结束
		removeEvent(this.wrapper, 'webkitTransitionEnd', this._transitionEnd); // 动画结束
		removeEvent(window, 'resize', this.refresh); // resize重新计算尺寸
		return null;
	};
	window.HSwipe = HSwipe;
}(window, document));
